#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Sat Jun 23 22:52:22 2018
@project: 天池比赛-A股主板上市公司公告信息抽取
@group: MZH_314
@author: LHQ
"""
import re


class CompanyAlias:
    """公司别名

    针对公告抽取过程中出现的公司简称，需要还原成全称， 该类实现了自动
    从文本中发现公司简称、根据公司简称找到对应的全称、得到所有的‘简称-全称’
    字典映射的功能

    Attributes
    ----------
    texts : iterable
        公告的文本内容，用于从中找到公司全称和简称

    recognize : function， 默认为None
        命名实体识别函数，接收一个文本字符串，
        返回其中的所有公司实体名的列表

    template : str
        含简称的正则模板
    """
    def __init__(self, texts, recognize=None):
        self.texts = self._process_texts(texts)
        self.recognize = recognize
        self.template = "(?:简称|下称)\W*?(?P<shortname>%s)\W*"
        
    def _process_texts(self, texts):
        """分割文本
        """
        new_texts = []
        for text in texts:
            for txt in re.split("[，。、；]", text):
                new_texts.append(re.sub("\s", "", txt))
        return new_texts
                
    def get_allshortname(self):
        """获取公告文本里的所有简称

        Returns
        -------
        shortnames: iterable
            texs里出现的所有简称
        """
        pattern = re.compile(self.template % "\w+")
        shortnames = []
        for text in self.texts:
            for m in pattern.finditer(text):
                shortnames.append(m.group('shortname'))
        return shortnames
    
    def recognize_fullname(self, shortname_text, shortname):
        """用recognize从含简称的短文本中抽取全称

        Args
        ----
        shortname_text : str
            含有简称的文本,全称在简称前面，简称后面没有其他公司名称

        shortname : str
            公司简称

        Returns
        ------
        fullname : str, 没找到则返回None
            简称对应的全称
        """
        if self.recognize is None:
            return None
        
        fullnames = self.recognize(re.split(self.template % shortname, shortname_text)[0])
        try:
            fullname = fullnames[-1]
        except IndexError:
            fullname = None
        finally:
            return fullname
        
    def re_fullname(self, shortname_text, shortname):
        """通过正则表达式从含简称的短文本中抽取全称

        Args
        ----
        shortname_text : str
            含有简称的文本,全称在简称前面，简称后面没有其他公司名称

        shortname : str
            公司简称

        Returns
        -------
        fullname : str, 没找到则返回None
            简称对应的全称
        """
        shortname_text = re.sub(".*(?:股东|关联方|一致行动人|收到|接到)", "", shortname_text)
#        print(shortname_text)
        p_0 = self.template % shortname
        p = "(?P<fullname>.*)\W\w*%s" % p_0
#        print(p)
        m = re.search(p, shortname_text)
        if m:
            fullname = m.group("fullname")
        else:
            fullname = None
        return fullname
        
    def get_fullname_for_short(self, shortname:str):
        """获取给定公司简称的全称

        Args
        ----
        shortname : str
            公司简称

        Returns
        -------
        fullname : str
            shortname对应的全称，没找到则返回None
        """
        p = re.compile(self.template % shortname)
        key_text = ''
        for text in self.texts:
            m = p.search(text)
            if m:
                _, end = m.span()
                key_text = text[:end]
                break
        else:
            return None
#        print(key_text)
        fullname = self.recognize_fullname(key_text, shortname)
        if fullname is None:
            fullname = self.re_fullname(key_text, shortname)
        return fullname
        
    
    def get_allalias(self):
        """获取文本里所有的’简称-全称‘映射
        
        Returns
        -------
            alias: 简称-全称 字典
        """
        d = {}
        shortnames = self.get_allshortname()
        for shortname in shortnames:
            d[shortname] = self.get_fullname_for_short(shortname)
        return d
